

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity I2CmasterTestbench is
end I2CmasterTestbench;

architecture I2Cwrite of I2CmasterTestbench is
  component I2Cslave_debug is
    port( --inputs from bus
          Data : inout std_logic;
          Clk : in std_logic
        );
  end component;

  signal i2c_clk : std_logic:='1';
  signal i2c_data : std_logic:='0';
begin
  
end architecture;

architecture I2Cwrite8 of I2CmasterTestbench is
  component I2Cmaster is
    Generic (register_data_width : natural;
             register_id_width : natural);
    Port ( PS2_Data : inout  STD_LOGIC;
           PS2_Clk : in  STD_LOGIC;
           FPGAClk : in std_logic;
           Send : in std_logic;
           Instruction : in std_logic_vector(7 downto 0);
           register_id : in std_logic_vector(register_id_width-1 downto 0);
           Data : inout std_logic_vector(register_data_width-1 downto 0)); 
  end component;

  signal buf : std_logic:='Z';
  signal i2c_clk,fpga_clk,send : std_logic:='0';
  signal i2c_data,dir : std_logic:='1';
  signal address_rw : std_logic_vector(7 downto 0):="10101011";   -- XXXXXXX Z (7 bits address) + (1 bit R(0)/W(1))
  signal reg,address_out : std_logic_vector(7 downto 0):="10000001";  --register address
  signal data : std_logic_vector(7 downto 0):="11001001"; --data
begin
  
  UUT: I2Cmaster 
  generic map(8,8)
  port map(i2c_data,i2c_clk,fpga_clk,send,address_rw,address_out,data);
  
  fpga_clk<= not fpga_clk after 10 ns; --50MHz (20ns per period)
  i2c_clk<= not i2c_clk after 5 us; --100kHz (10us per period)
  
  ------------------------------
	-- In/Out port
	------------------------------
	process (fpga_clk,i2c_data,dir)
	begin
	    if rising_edge(fpga_clk) then
	       if dir = '1' then
	           buf <= i2c_data;
	       end if;
	    end if;
	end process;
	
	process (fpga_clk,dir,buf)
	begin
	    if dir = '0' then
	        i2c_data <= buf;
	    else
	        i2c_data <= 'Z';
	    end if;
	end process;
  ------------------------------
  
  test: process
  begin
    buf<='Z';
    wait for 100 us;  --setup
    --send bit, activate master
    send<='1';
    wait for 10 us;
    
    --slave address
    wait for 80 us;   
    
    --ack
    wait for 3 us;
    dir<='0';
    buf<='0';
    wait for 6 us;
    dir<='1';
    buf<='Z';
    wait for 1 us;
    
    --register address
    wait for 80 us;
    
    --ack
    wait for 3 us;
    dir<='0';
    buf<='0';
    wait for 6 us;
    dir<='1';
    buf<='Z';
    wait for 1 us;
    
    --data
    wait for 80 us;
    
    --ack
    wait for 3 us;
    dir<='0';
    buf<='0';
    wait for 6 us;
    dir<='1';
    buf<='Z';
    wait for 1 us;
    
    wait;
  end process;
end architecture;

architecture I2Cread8 of I2CmasterTestbench is
  component I2Cmaster is
    Generic (register_data_width : natural;
             register_id_width : natural);
    Port ( PS2_Data : inout  STD_LOGIC;
           PS2_Clk : in  STD_LOGIC;
           FPGAClk : in std_logic;
           Send : in std_logic;
           Instruction : in std_logic_vector(7 downto 0);
           register_id : in std_logic_vector(register_id_width-1 downto 0);
           Data : inout std_logic_vector(register_data_width-1 downto 0)); 
  end component;

  signal buf : std_logic:='Z';
  signal i2c_clk,fpga_clk,send : std_logic:='0';
  signal i2c_data,dir : std_logic:='1';
  signal address_rw : std_logic_vector(7 downto 0):="10101010";   -- XXXXXXX Z (7 bits address) + (1 bit R(0)/W(1))
  signal reg,address_out : std_logic_vector(7 downto 0):="10000001";  --register address
  signal data : std_logic_vector(7 downto 0):="11001001"; --data
begin
  
  UUT: I2Cmaster 
  generic map(8,8)
  port map(i2c_data,i2c_clk,fpga_clk,send,address_rw,address_out,data);
  
  fpga_clk<= not fpga_clk after 10 ns; --50MHz (20ns per period)
  i2c_clk<= not i2c_clk after 5 us; --100kHz (10us per period)
  
  ------------------------------
	-- In/Out port
	------------------------------
	process (fpga_clk,i2c_data,dir)
	begin
	    if rising_edge(fpga_clk) then
	       if dir = '1' then
	           buf <= i2c_data;
	       end if;
	    end if;
	end process;
	
	process (fpga_clk,dir,buf)
	begin
	    if dir = '0' then
	        i2c_data <= buf;
	    else
	        i2c_data <= 'Z';
	    end if;
	end process;
  ------------------------------
  
  test: process
  begin
    buf<='Z';
    wait for 100 us;  --setup
    --send bit, activate master
    send<='1';
    wait for 10 us;
    send<='0';
    
    --slave address
    wait for 80 us;   
    
    --ack
    wait for 3 us;
    dir<='0';
    buf<='0';
    wait for 6 us;
    dir<='1';
    buf<='Z';
    wait for 1 us;
    
    --register address
    wait for 80 us;
    
    --ack
    wait for 3 us;
    dir<='0';
    buf<='0';
    wait for 6 us;
    dir<='1';
    buf<='Z';
    wait for 500 ns;
    
    --data
    dir<='0';
    buf<='1';
    wait for 500 ns;
    for i in 7 downto 0 loop
      wait for 3 us;  --middle of low trough
      buf<=data(i);
      wait for 7 us;  --end of clock cycle
    end loop;
    dir<='1';
    buf<='Z';
    
    --ack
    wait for 10 us;
    
    wait;
  end process;
end architecture;